package com.tencreat.service.account.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tencreat.common.core.HttpResult;
import com.tencreat.common.core.domain.entity.SysUser;
import com.tencreat.common.core.domain.model.*;
import com.tencreat.common.core.service.TokenService;
import com.tencreat.common.enums.ActionMessageType;
import com.tencreat.common.enums.UserType;
import com.tencreat.common.enums.account.CitySmsTypeEnum;
import com.tencreat.common.enums.account.TencreatTips;
import com.tencreat.common.enums.mall.AllEnum;
import com.tencreat.common.exception.CustomException;
import com.tencreat.common.utils.RabbitSendUtils;
import com.tencreat.common.utils.SecurityUtils;
import com.tencreat.common.utils.StringUtils;
import com.tencreat.common.utils.bean.BeanUtils;
import com.tencreat.common.utils.sign.Md5Utils;
import com.tencreat.domain.account.AccountLoginCheck;
import com.tencreat.domain.account.CodeAndType;
import com.tencreat.domain.account.MallSupplier;
import com.tencreat.domain.account.MallStore;
import com.tencreat.domain.account.MallUser;
import com.tencreat.domain.account.dto.AccountLoginDTO;
import com.tencreat.domain.account.dto.AccountPhoneAndCodeDTO;
import com.tencreat.domain.account.dto.AccountRegisterDTO;
import com.tencreat.domain.account.dto.UpdateNewPhoneDTO;
import com.tencreat.domain.account.vo.ResAccountLogin;
import com.tencreat.mapper.account.AccountLoginCheckMapper;
import com.tencreat.service.account.IAccountLoginCheckService;
import com.tencreat.service.account.IMallStoreService;
import com.tencreat.service.account.IMallSupplierService;
import com.tencreat.service.account.IMallUserService;
import com.tencreat.service.mall.IMallGoodsCutService;
import com.tencreat.service.mall.IRechargeLimitChangeService;
import com.tencreat.service.system.ISysMessageService;
import com.tencreat.service.system.ISysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 登录 用户类型Service业务层处理
 *
 * @author tencreat
 * @date 2021-09-06
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class AccountLoginCheckServiceImpl extends ServiceImpl<AccountLoginCheckMapper, AccountLoginCheck> implements IAccountLoginCheckService {

    private final TokenService tokenService;
    private final IMallUserService mallUserService;
    private final ISysUserService sysUserService;
    private final ISysMessageService sysMessageService;
    private final RabbitSendUtils rabbitSendUtils;

    /**
     * 查询登录 用户类型
     *
     * @param id 登录 用户类型ID
     * @return 登录 用户类型
     */
    @Override
    public AccountLoginCheck selectAccountLoginCheckById(ReqIdParam id) {
        return baseMapper.selectById(id.getId());
    }

    /**
     * 查询登录 用户类型列表
     *
     * @param accountLoginCheck 登录 用户类型
     * @return 登录 用户类型
     */
    @Override
    public List<AccountLoginCheck> selectAccountLoginCheckList(AccountLoginCheck accountLoginCheck) {
        return baseMapper.selectList(Wrappers.query(accountLoginCheck));
    }

    /**
     * 新增登录 用户类型
     *
     * @param accountLoginCheck 登录 用户类型
     * @return 结果
     */
    @Override
    public int insertAccountLoginCheck(AccountLoginCheck accountLoginCheck) {
        accountLoginCheck.setCreateTime(LocalDateTime.now());
        return baseMapper.insert(accountLoginCheck);
    }

    /**
     * 修改登录 用户类型
     *
     * @param accountLoginCheck 登录 用户类型
     * @return 结果
     */
    @Override
    public int updateAccountLoginCheck(AccountLoginCheck accountLoginCheck) {
        accountLoginCheck.setUpdateTime(LocalDateTime.now());
        return baseMapper.updateById(accountLoginCheck);
    }

    /**
     * 批量删除登录 用户类型
     *
     * @param ids 需要删除的登录 用户类型ID
     * @return 结果
     */
    @Override
    public int deleteAccountLoginCheckByIds(ReqIdsParam ids) {
        return baseMapper.deleteBatchIds(ids.getId());
    }

    /**
     * 删除登录 用户类型信息
     *
     * @param id 登录 用户类型ID
     * @return 结果
     */
    @Override
    public int deleteAccountLoginCheckById(ReqIdParam id) {
        return baseMapper.deleteById(id.getId());
    }

    @Override
    public HttpResult<ResAccountLogin> login(AccountLoginDTO accountLoginPo) {
        AccountLoginCheck loginCheck = lambdaQuery().eq(AccountLoginCheck::getPhone, accountLoginPo.getPhone()).one();
        if (loginCheck == null) {
            return HttpResult.error("当前手机未注册");
        }
        if (!loginCheck.getPassword().equalsIgnoreCase(accountLoginPo.getPassword())) {
            return HttpResult.error("密码错误");
        }
        AccountLogin accountLogin = new AccountLogin();
        BeanUtils.copyProperties(loginCheck, accountLogin);
        LoginUser loginUser = new LoginUser(accountLogin);
        ResAccountLogin accountLoginBO = new ResAccountLogin();
        MallUser mallUser = mallUserService.getOne(new QueryWrapper<MallUser>().eq("uuid", loginCheck.getUuid()));
        if (mallUser.getStatus() != 0) {
            return HttpResult.error("该账户已被冻结");
        }
        BeanUtils.copyBeanProp(accountLoginBO, mallUser);
        accountLoginBO.setToken(tokenService.createToken(loginUser));

        // 发送登录事件
        rabbitSendUtils.sendActionMessage(mallUser.getUuid(), ActionMessageType.LOGIN, accountLoginPo.getPlatformID());

        return HttpResult.ok(accountLoginBO);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public HttpResult<String> register(AccountRegisterDTO accountRegisterPo) {
        log.info("注册开始时间{},手机号{}", DateUtil.now(), accountRegisterPo.getPhone());
        AccountLoginCheck accountLoginCheck = lambdaQuery()
                .eq(AccountLoginCheck::getPhone, accountRegisterPo.getPhone()).one();
        if (accountLoginCheck != null) {
            return HttpResult.error("该手机号已被注册");
        }
        if (accountRegisterPo.getReferrerUuid() == null || accountRegisterPo.getReferrerUuid() == 0) {
            accountRegisterPo.setReferrerUuid(AllEnum.SUPER_UUID);
        }
        MallUser mallUserServiceOne = mallUserService
                .getOne(new QueryWrapper<MallUser>().eq("uuid", accountRegisterPo.getReferrerUuid()));
        if (mallUserServiceOne == null) {
            return HttpResult.error(TencreatTips.Account.RECOMMEND_CODE_NOT_EXIST);
        }

        // 校验验证码
        sysMessageService.verifySmsCode(CitySmsTypeEnum.REGISTERED, accountRegisterPo.getPhone(), accountRegisterPo.getCode());

        if (accountRegisterPo.getUserType().equals(UserType.ORDINARY.getValue())) {
            Long uuid = (long) mallUserService.generateUUID();
            log.info("生成UUID{}", uuid);
            AccountLoginCheck loginCheck = new AccountLoginCheck();
//			loginCheck.setPassword(Md5Utils.hash(accountRegisterPo.getPassword()));
            loginCheck.setPassword(accountRegisterPo.getPassword());
            loginCheck.setPhone(accountRegisterPo.getPhone());
            loginCheck.setUserType(accountRegisterPo.getUserType());
            loginCheck.setCreateTime(LocalDateTime.now());
            loginCheck.setUuid(uuid);
            baseMapper.insert(loginCheck);
            MallUser mallUser = new MallUser();
            mallUser.setMobile(accountRegisterPo.getPhone());
            mallUser.setUuid(uuid);
            mallUser.setUsername(accountRegisterPo.getPhone());
            mallUser.setPassword(accountRegisterPo.getPassword());
            String unionId = accountRegisterPo.getUnionId();
            mallUser.setUnionId(unionId);
            mallUser.setWeixinOpenid(accountRegisterPo.getWxOpenId());

            //第一次生成的昵称中间四位显示星号
            String first = accountRegisterPo.getPhone().substring(0, 3);
            String end = accountRegisterPo.getPhone().substring(accountRegisterPo.getPhone().length() - 4);
            String nickName=first+"****"+end;
            mallUser.setNickname(nickName);

            mallUser.setReferrerUuid(accountRegisterPo.getReferrerUuid());
            List<String> classRelationsList = StrUtil.splitTrim(mallUserServiceOne.getClassRelations(), ",");
            classRelationsList.add(accountRegisterPo.getReferrerUuid().toString());
            mallUser.setTier(classRelationsList.size());
            mallUser.setClassRelations(StrUtil.join(",", classRelationsList));
            mallUser.setCreateTime(LocalDateTime.now());
            if (StrUtil.isNotEmpty(mallUser.getUnionId())) {
                int count = mallUserService.lambdaQuery().eq(MallUser::getUnionId, mallUser.getUnionId()).count();
                if (count > 0) {
                    throw new CustomException("该微信已绑定账号");
                }
            }
            mallUserService.insertMallUser(mallUser);




            return HttpResult.ok("注册成功");
        }
        return null;
    }

    @Override
    @Transactional
    public HttpResult<String> forgetPassword(AccountPhoneAndCodeDTO accountPhoneAndCodePO) {

        // 校验验证码
        sysMessageService.verifySmsCode(CitySmsTypeEnum.FORGET_PASSWORD, accountPhoneAndCodePO.getPhone(), accountPhoneAndCodePO.getCode());

        AccountLoginCheck accountLoginCheck = lambdaQuery()
                .eq(AccountLoginCheck::getPhone, accountPhoneAndCodePO.getPhone()).one();
        accountLoginCheck.setPassword(Md5Utils.hash(accountPhoneAndCodePO.getPassword()));
        baseMapper.updateById(accountLoginCheck);
        MallUser mallUser = mallUserService
                .getOne(new QueryWrapper<MallUser>().eq("mobile", accountPhoneAndCodePO.getPhone()));
        mallUser.setPassword(Md5Utils.hash(accountPhoneAndCodePO.getPassword()));
        mallUserService.updateMallUser(mallUser);
        return HttpResult.ok(TencreatTips.Account.RESET_PASSWORD_SUCCESS);
    }

    @Override
    @Transactional
    public HttpResult<String> updatePassword(AccountPhoneAndCodeDTO accountPhoneAndCodePO) {
        // 校验验证码
        sysMessageService.verifySmsCode(CitySmsTypeEnum.UPDATE_PASSWORD, accountPhoneAndCodePO.getPhone(), accountPhoneAndCodePO.getCode());

        AccountLoginCheck accountLoginCheck = lambdaQuery()
                .eq(AccountLoginCheck::getPhone, accountPhoneAndCodePO.getPhone()).one();
        accountLoginCheck.setPassword(Md5Utils.hash(accountPhoneAndCodePO.getPassword()));
        baseMapper.updateById(accountLoginCheck);
        MallUser mallUser = mallUserService
                .getOne(new QueryWrapper<MallUser>().eq("mobile", accountPhoneAndCodePO.getPhone()));
        mallUser.setPassword(Md5Utils.hash(accountPhoneAndCodePO.getPassword()));
        mallUserService.updateMallUser(mallUser);
        return HttpResult.ok(TencreatTips.Account.RESET_PASSWORD_SUCCESS);
    }

    @Override
    @Transactional
    public HttpResult<String> chickPhone(CodeAndType codeAndType, LoginUser loginUser) {

        if (CitySmsTypeEnum.CHECK_OLD_PHONE.getType().equals(codeAndType.getType())) {
            // 校验验证码
            sysMessageService.verifySmsCode(CitySmsTypeEnum.CHECK_OLD_PHONE, codeAndType.getPhone(), codeAndType.getCode());
        }
        if (CitySmsTypeEnum.CHECK_NEW_PHONE.getType().equals(codeAndType.getType())) {
            // 校验验证码
            sysMessageService.verifySmsCode(CitySmsTypeEnum.CHECK_NEW_PHONE, codeAndType.getPhone(), codeAndType.getCode());
        }

        if (CitySmsTypeEnum.CHECK_NEW_PHONE.getType().equals(codeAndType.getType())) {
            AccountLoginCheck accountLoginCheck = lambdaQuery()
                    .eq(AccountLoginCheck::getUuid, loginUser.getAccountLogin().getUuid()).one();
            MallUser mallUser = mallUserService
                    .getOne(new QueryWrapper<MallUser>().eq("uuid", loginUser.getAccountLogin().getUuid()));
            mallUser.setMobile(codeAndType.getPhone());
            mallUserService.updateMallUser(mallUser);
            accountLoginCheck.setPhone(codeAndType.getPhone());
            baseMapper.updateById(accountLoginCheck);
            return HttpResult.okMsg("修改成功！");
        }
        return HttpResult.okMsg("验证成功");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void changePhone(UpdateNewPhoneDTO updateNewPhoneDTO) {
        Long uuid = SecurityUtils.getLoginUser().getAccountLogin().getUuid();
        String phone = SecurityUtils.getLoginUser().getAccountLogin().getPhone();
        updateNewPhoneDTO.setOldPhone(phone);
        if (phone.equals(updateNewPhoneDTO.getNewPhone())) {
            throw new CustomException("旧手机号与新手机号一样");
        }
        updatePhone(updateNewPhoneDTO, uuid);
    }

    @Override
    public void updatePhone(UpdateNewPhoneDTO updateNewPhoneDTO, Long uuid) {
        MallUser one = mallUserService.lambdaQuery().eq(MallUser::getUuid, uuid).one();
        //是供应商修改供应商号码
        if (one.getSupplier() == AllEnum.SupplierGoods.YES.getType()) {
            SysUser newUser = sysUserService.selectUserByPhone(updateNewPhoneDTO.getNewPhone(), 2);
            SysUser oldUser = sysUserService.selectUserByPhone(updateNewPhoneDTO.getOldPhone(), 2);
            if (newUser != null) {
                throw new CustomException("供应商中已存在该手机号");
            }
            if (oldUser == null) {
                throw new CustomException("该手机号数据错误，请联系管理员！");
            }
            SysUser user = new SysUser();
            user.setUserId(oldUser.getUserId());
            user.setPhonenumber(updateNewPhoneDTO.getNewPhone());
            user.setUserName(updateNewPhoneDTO.getNewPhone());
            sysUserService.updateUserProfile(user);

            SpringUtil.getBean(IMallSupplierService.class).lambdaUpdate()
                    .set(MallSupplier::getMobile, updateNewPhoneDTO.getNewPhone())
                    .set(MallSupplier::getAccount, updateNewPhoneDTO.getNewPhone())
                    .eq(MallSupplier::getMobile, updateNewPhoneDTO.getOldPhone())
                    .update();
        }
        if (one.getStore() == AllEnum.StoreGoods.YES.getType()) {
            SysUser newUser = sysUserService.selectUserByPhone(updateNewPhoneDTO.getNewPhone(), 1);
            SysUser oldUser = sysUserService.selectUserByPhone(updateNewPhoneDTO.getOldPhone(), 1);
            if (newUser != null) {
                throw new CustomException("店铺商家中已存在该手机号");
            }
            if (oldUser == null) {
                throw new CustomException("该手机号数据错误，请联系管理员！");
            }
            SysUser user = new SysUser();
            user.setUserId(oldUser.getUserId());
            user.setPhonenumber(updateNewPhoneDTO.getNewPhone());
            user.setUserName(updateNewPhoneDTO.getNewPhone());
            sysUserService.updateUserProfile(user);

            SpringUtil.getBean(IMallStoreService.class).lambdaUpdate()
                    .set(MallStore::getMobile, updateNewPhoneDTO.getNewPhone())
                    .set(MallStore::getAccount, updateNewPhoneDTO.getNewPhone())
                    .eq(MallStore::getMobile, updateNewPhoneDTO.getOldPhone())
                    .update();
        }
        // 更改登录信息
        boolean isU = lambdaUpdate()
                .set(AccountLoginCheck::getPhone, updateNewPhoneDTO.getNewPhone())
                .eq(AccountLoginCheck::getUuid, uuid)
                .update();
        if (!isU) {
            throw new CustomException("用户已修改或不存在");
        }

        //修改用户的信息
        mallUserService.lambdaUpdate()
                .set(MallUser::getMobile, updateNewPhoneDTO.getNewPhone())
                .set(MallUser::getUsername, updateNewPhoneDTO.getNewPhone())
                .eq(MallUser::getUsername, updateNewPhoneDTO.getOldPhone())
                .eq(MallUser::getUuid, uuid)
                .update();
        // 修改邀请手机号
        mallUserService.lambdaUpdate()
                .set(MallUser::getUpMobile, updateNewPhoneDTO.getNewPhone())
                .eq(MallUser::getReferrerUuid, uuid)
                .update();
    }



}

